﻿using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using EdlinSoftware.RegexTester.Code;
using EdlinSoftware.RegexTester.Properties;

namespace EdlinSoftware.RegexTester
{
    /// <summary>
    /// Form for testng of regular expressions.
    /// </summary>
    public partial class MainForm : Form
    {
        #region Constructors
        /// <summary>
        /// Initializes MainForm instance.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            fileShortcuts.TextBox = tbText;
        }
        #endregion

        #region Event handlers

        #region Form event handlers
        private void MainForm_Load(object sender, EventArgs e)
        {
            clbOptions.ShowOptions();
            cbRegex.MaximumLinesNumber = Settings.Default.SizeOfRegexStorage;
            cbRegex.LoadStoredExpressions();
            new FileShortcutsProvider().LoadShortcuts();
            fileShortcuts.ShowFileShortcuts();
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            cbRegex.SaveExpressions();
        }
        #endregion

        #region Menu event handlers
        private void miExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void miEnglish_Click(object sender, EventArgs e)
        {
            Settings.Default.UICulture = "en-US";
            Settings.Default.Save();
            MessageBox.Show(
                Resources.Restart,
                Resources.Information,
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }

        private void miRussian_Click(object sender, EventArgs e)
        {
            Settings.Default.UICulture = "ru-RU";
            Settings.Default.Save();
            MessageBox.Show(
                Resources.Restart,
                Resources.Information,
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }

        private void miOpen_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                Encoding encoding;
                switch (openFileDialog.FilterIndex)
                {
                    case 2:
                        {
                            encoding = Encoding.UTF8;
                            break;
                        }
                    case 3:
                        {
                            encoding = Encoding.Unicode;
                            break;
                        }
                    default:
                        {
                            encoding = Encoding.Default;
                            break;
                        }
                }

                OpenFile(openFileDialog.FileName, encoding);
            }
        }

        private void miOptionsDialog_Click(object sender, EventArgs e)
        {
            cbRegex.SaveExpressions();
            new SettingsForm() { RegexStorageFileName = cbRegex.StorageFileName }.ShowDialog(this);
            fileShortcuts.ShowFileShortcuts();
            cbRegex.LoadStoredExpressions();
            cbRegex.MaximumLinesNumber = Settings.Default.SizeOfRegexStorage;
        }

        private void miAbout_Click(object sender, EventArgs e)
        {
            new AboutForm().ShowDialog(this);
        }
        #endregion

        #region Buttons event handlers
        private void btnFind_Click(object sender, EventArgs e)
        {
            try
            {
                Regex regex = cbRegex.GetRegularExpression(clbOptions.GetOptions());

                MatchCollection matches = regex.Matches(tbText.Text);
                tvResults.ShowMatches(matches);
            }
            catch (Exception ex)
            {
                ShowExceptionInformation(ex);
            }
        }

        private void btnReplace_Click(object sender, EventArgs e)
        {
            try
            {
                Regex regex = cbRegex.GetRegularExpression(clbOptions.GetOptions());

                MatchCollection matches = regex.Matches(tbText.Text);
                tvResults.ShowMatches(matches);
                tbReplaceResult.Text = regex.Replace(tbText.Text, tbReplace.Text);
            }
            catch (Exception ex)
            {
                ShowExceptionInformation(ex);
            }
        }

        private void btnSplit_Click(object sender, EventArgs e)
        {
            try
            {
                Regex regex = cbRegex.GetRegularExpression(clbOptions.GetOptions());

                MatchCollection matches = regex.Matches(tbText.Text);
                tvResults.ShowMatches(matches);

                tbSplitResult.Text = string.Join(Environment.NewLine, regex.Split(tbText.Text));
            }
            catch (Exception ex)
            {
                ShowExceptionInformation(ex);
            }
        }

        private void btnCompile_Click(object sender, EventArgs e)
        {
            ValidateChildren();

            if (!Regex.IsMatch(tbNameOfClass.Text, @"^\w+$"))
            { return; }

            if (!Regex.IsMatch(tbNamespace.Text, @"^\w+(.\w+)*$"))
            { return; }

            try
            {
                RegexOptions options = clbOptions.GetOptions();
                options &= ~RegexOptions.Compiled;

                cbRegex.GetRegularExpression(options);

                RegexCompilationInfo compilationInfo = new RegexCompilationInfo(cbRegex.Text, options, tbNameOfClass.Text, tbNamespace.Text, true);

                if (compileDialog.ShowDialog(this) == DialogResult.OK)
                {
                    AssemblyName assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(compileDialog.FileName));
                    assemblyName.CodeBase = Path.GetDirectoryName(compileDialog.FileName);

                    Regex.CompileToAssembly(new[] { compilationInfo }, assemblyName);

                    MessageBox.Show(
                        Resources.CompilationOk,
                        Resources.Information,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                ShowExceptionInformation(ex);
            }
        }

        #endregion

        private void tvResults_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Tag is Capture)
            {
                Capture cap = (Capture)e.Node.Tag;
                tbText.Select(cap.Index, cap.Length);
                tbText.ScrollToCaret();
            }
        }

        private void tbNameOfClass_Validated(object sender, EventArgs e)
        {
            if (Regex.IsMatch(tbNameOfClass.Text, @"^\w+$"))
            {
                errorProvider.SetError(tbNameOfClass, null);
            }
            else
            {
                errorProvider.SetError(tbNameOfClass, Resources.NameOfClass);
            }
        }

        private void tbNamespace_Validated(object sender, EventArgs e)
        {
            if (Regex.IsMatch(tbNamespace.Text, @"^\w+(.\w+)*$"))
            {
                errorProvider.SetError(tbNamespace, null);
            }
            else
            {
                errorProvider.SetError(tbNamespace, Resources.Namespace);
            }
        }

        #endregion

        #region Methods

        private void OpenFile(string filePath, Encoding encoding)
        {
            try
            {
                tbText.Text = File.ReadAllText(filePath, encoding);
            }
            catch (Exception ex)
            {
                ShowExceptionInformation(ex);
            }
        }

        private static void ShowExceptionInformation(Exception ex)
        {
            MessageBox.Show(
                ex.ToString(),
                Resources.Error,
                MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        }

        #endregion
    }
}